Bring up AP of VMX domain.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 24 Feb 2006 16:32:58 +0000 (17:32 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Fri, 24 Feb 2006 16:32:58 +0000 (17:32 +0100)
1) add INIT-SIPI-SIPI IPI sequence handling code to HVM virtual lapic
code.
2) add an new interface init_ap_context to hvm_funcs, and implement the
VMX side.
3) add a hvm generic function hvm_bringup_ap, which in turn calls
init_ap_context.

Signed-off-by: Xin Li <xin.b.li@intel.com>
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/vlapic.c
xen/arch/x86/hvm/vmx/io.c
xen/arch/x86/hvm/vmx/vmx.c
xen/include/asm-x86/hvm/hvm.h
xen/include/asm-x86/hvm/vcpu.h
xen/include/asm-x86/hvm/vlapic.h

index cff7af1382a81282ef06aa3ef7ba0266970c927d..d0f9ccdffba45254c3889e92a6cd176f192ed474 100644 (file)
@@ -25,6 +25,7 @@
 #include <xen/sched.h>
 #include <xen/irq.h>
 #include <xen/softirq.h>
+#include <xen/domain.h>
 #include <xen/domain_page.h>
 #include <asm/current.h>
 #include <asm/io.h>
@@ -59,9 +60,9 @@ static void hvm_zap_mmio_range(
 
     for ( i = 0; i < nr_pfn; i++ )
     {
-        if ( pfn + i >= 0xfffff ) 
+        if ( pfn + i >= 0xfffff )
             break;
-        
+
         __copy_to_user(&phys_to_machine_mapping[pfn + i], &val, sizeof (val));
     }
 }
@@ -217,7 +218,7 @@ void hvm_pic_assist(struct vcpu *v)
     global_iodata_t *spg;
     u16   *virq_line, irqs;
     struct hvm_virpic *pic = &v->domain->arch.hvm_domain.vpic;
-    
+
     spg = &get_sp(v->domain)->sp_global;
     virq_line  = &spg->pic_clear_irr;
     if ( *virq_line ) {
@@ -311,6 +312,52 @@ void hvm_print_line(struct vcpu *v, const char c)
        pbuf[(*index)++] = c;
 }
 
+/*
+ * only called in HVM domain BSP context
+ * when booting, vcpuid is always equal to apic_id
+ */
+int hvm_bringup_ap(int vcpuid, int trampoline_vector)
+{
+    struct vcpu *bsp = current, *v;
+    struct domain *d = bsp->domain;
+    struct vcpu_guest_context *ctxt;
+    int rc = 0;
+
+    /* current must be HVM domain BSP */
+    if ( !(HVM_DOMAIN(bsp) && bsp->vcpu_id == 0) ) {
+        printk("Not calling hvm_bringup_ap from BSP context.\n");
+        domain_crash_synchronous();
+    }
+
+    if ( (v = d->vcpu[vcpuid]) == NULL )
+        return -ENOENT;
+
+    if ( (ctxt = xmalloc(struct vcpu_guest_context)) == NULL ) {
+        printk("Failed to allocate memory in hvm_bringup_ap.\n");
+        return -ENOMEM;
+    }
+
+    hvm_init_ap_context(ctxt, vcpuid, trampoline_vector);
+
+    LOCK_BIGLOCK(d);
+    rc = -EEXIST;
+    if ( !test_bit(_VCPUF_initialised, &v->vcpu_flags) )
+        rc = boot_vcpu(d, vcpuid, ctxt);
+    UNLOCK_BIGLOCK(d);
+
+    if ( rc != 0 )
+        printk("AP %d bringup failed in boot_vcpu %x.\n", vcpuid, rc);
+    else {
+        if ( test_and_clear_bit(_VCPUF_down, &d->vcpu[vcpuid]->vcpu_flags) )
+            vcpu_wake(d->vcpu[vcpuid]);
+        printk("AP %d bringup suceeded.\n", vcpuid);
+    }
+
+    xfree(ctxt);
+
+    return rc;
+}
+
 /*
  * Local variables:
  * mode: C
index 156e7fa68c6c1a05debf79604da0eba4b62dc4e2..aa74430159a502d2244c25fb3c59d18eab67224a 100644 (file)
@@ -225,27 +225,35 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
         break;
 
     case VLAPIC_DELIV_MODE_INIT:
-        if (!level && trig_mode == 1) {        //Deassert
+        if ( !level && trig_mode == 1 ) {        //Deassert
             printk("This hvm_vlapic is for P4, no work for De-assert init\n");
         } else {
             /* FIXME How to check the situation after vcpu reset? */
-            vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
-            if (vlapic->vcpu) {
-                vcpu_pause(vlapic->vcpu);
+            if ( test_and_clear_bit(_VCPUF_initialised, &v->vcpu_flags) ) {
+                printk("Reset hvm vcpu not supported yet\n");
+                domain_crash_synchronous();
             }
+            v->arch.hvm_vcpu.init_sipi_sipi_state =
+                HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
+            result = 1;
         }
         break;
 
     case VLAPIC_DELIV_MODE_STARTUP:
-        if (vlapic->init_sipi_sipi_state != VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI)
+        if ( v->arch.hvm_vcpu.init_sipi_sipi_state ==
+                HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM )
             break;
-        vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_NORM;
-        if (!vlapic->vcpu) {
-            /* XXX Call hvm_bringup_ap here */
-             result = 0;
-        }else{
-            //hvm_vcpu_reset(vlapic->vcpu);
+
+        v->arch.hvm_vcpu.init_sipi_sipi_state =
+                HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM;
+
+        if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) {
+            printk("SIPI for initialized vcpu vcpuid %x\n", v->vcpu_id);
+            domain_crash_synchronous();
         }
+
+        if ( hvm_bringup_ap(v->vcpu_id, vector) != 0 )
+            result = 0;
         break;
 
     default:
index f836994d2efd29015a05f8745d4932631a74984f..6c129f34e0f36a759acce6f2aa1c80578c5b37e3 100644 (file)
@@ -113,13 +113,15 @@ asmlinkage void vmx_intr_assist(void)
     struct hvm_virpit *vpit = &plat->vpit;
     struct hvm_virpic *pic= &plat->vpic;
 
-    hvm_pic_assist(v);
-    __vmread_vcpu(v, CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
-    if ( vpit->pending_intr_nr ) {
+    if ( v->vcpu_id == 0 )
+        hvm_pic_assist(v);
+
+    if ( (v->vcpu_id == 0) && vpit->pending_intr_nr ) {
         pic_set_irq(pic, 0, 0);
         pic_set_irq(pic, 0, 1);
     }
 
+    __vmread_vcpu(v, CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
     __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
 
     if (intr_fields & INTR_INFO_VALID_MASK) {
index f9f5748d5cb18923deebbe0c6979a434efbe863c..5da0eff0d49c907f54bb83e8569e2d4edc052bf4 100644 (file)
@@ -448,6 +448,37 @@ unsigned long vmx_get_ctrl_reg(struct vcpu *v, unsigned int num)
     return 0;                   /* dummy */
 }
 
+/* SMP VMX guest support */
+void vmx_init_ap_context(struct vcpu_guest_context *ctxt,
+                         int vcpuid, int trampoline_vector)
+{
+    int i;
+
+    memset(ctxt, 0, sizeof(*ctxt));
+
+    /*
+     * Initial register values:
+     */
+    ctxt->user_regs.eip = VMXASSIST_BASE;
+    ctxt->user_regs.edx = vcpuid;
+    ctxt->user_regs.ebx = trampoline_vector;
+
+    ctxt->flags = VGCF_HVM_GUEST;
+
+    /* Virtual IDT is empty at start-of-day. */
+    for ( i = 0; i < 256; i++ )
+    {
+        ctxt->trap_ctxt[i].vector = i;
+        ctxt->trap_ctxt[i].cs     = FLAT_KERNEL_CS;
+    }
+
+    /* No callback handlers. */
+#if defined(__i386__)
+    ctxt->event_callback_cs     = FLAT_KERNEL_CS;
+    ctxt->failsafe_callback_cs  = FLAT_KERNEL_CS;
+#endif
+}
+
 void do_nmi(struct cpu_user_regs *);
 
 static int check_vmx_controls(ctrls, msr)
@@ -545,6 +576,8 @@ int start_vmx(void)
     hvm_funcs.instruction_length = vmx_instruction_length;
     hvm_funcs.get_guest_ctrl_reg = vmx_get_ctrl_reg;
 
+    hvm_funcs.init_ap_context = vmx_init_ap_context;
+
     hvm_enabled = 1;
 
     return 1;
index c4afabcd439ed755300e4147fe0aab8668216f77..5df87f90ea2fa58771f95b63873bf46a0c8d7f03 100644 (file)
@@ -67,6 +67,9 @@ struct hvm_function_table {
     int (*paging_enabled)(struct vcpu *v);
     int (*instruction_length)(struct vcpu *v);
     unsigned long (*get_guest_ctrl_reg)(struct vcpu *v, unsigned int num);
+
+    void (*init_ap_context)(struct vcpu_guest_context *ctxt,
+                            int vcpuid, int trampoline_vector);
 };
 
 extern struct hvm_function_table hvm_funcs;
@@ -173,4 +176,14 @@ hvm_get_guest_ctrl_reg(struct vcpu *v, unsigned int num)
         return hvm_funcs.get_guest_ctrl_reg(v, num);
     return 0;                   /* force to fail */
 }
+
+static inline void
+hvm_init_ap_context(struct vcpu_guest_context *ctxt,
+                    int vcpuid, int trampoline_vector)
+{
+    return hvm_funcs.init_ap_context(ctxt, vcpuid, trampoline_vector);
+}
+
+extern int hvm_bringup_ap(int vcpuid, int trampoline_vector);
+
 #endif /* __ASM_X86_HVM_HVM_H__ */
index 5e0a11c40f213101c28cb3d4ee2e93f18c5176be..234b0d918634bb51d3bb243967d556a6dae871ca 100644 (file)
 #include <asm/hvm/vmx/vmcs.h>
 #include <asm/hvm/svm/vmcb.h>
 
+#define HVM_VCPU_INIT_SIPI_SIPI_STATE_NORM          0
+#define HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI     1
+
 struct hvm_vcpu {
-    unsigned long       ioflags;
-    struct mmio_op      mmio_op;
-    struct vlapic       *vlapic;
+    unsigned long   ioflags;
+    struct mmio_op  mmio_op;
+    struct vlapic   *vlapic;
+    /* For AP startup */
+    unsigned long   init_sipi_sipi_state;
 
     union {
         struct arch_vmx_struct vmx;
index 86fdcbca21a709294a3cd76c3870b7fff8673af1..8d3b9cf1d1ebc90b7a2578bf8d34535f0716051e 100644 (file)
@@ -159,9 +159,6 @@ typedef struct direct_intr_info {
     int source[6];
 } direct_intr_info_t;
 
-#define VLAPIC_INIT_SIPI_SIPI_STATE_NORM          0
-#define VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI     1
-
 struct vlapic
 {
     //FIXME check what would be 64 bit on EM64T
@@ -197,7 +194,6 @@ struct vlapic
     unsigned long      init_ticks;
     uint32_t           err_write_count;
     uint64_t           apic_base_msr;
-    uint32_t           init_sipi_sipi_state;
     struct vcpu        *vcpu;
     struct domain      *domain;
 };